package com.commerce.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.commerce.common.entity.Order;
import com.commerce.common.entity.Payment;
import com.commerce.common.entity.PaymentMethod;
import com.commerce.common.exception.BusinessException;
import com.commerce.order.mapper.PaymentMapper;
import com.commerce.order.mapper.PaymentMethodMapper;
import com.commerce.order.service.OrderService;
import com.commerce.order.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 支付服务实现
 */
@Slf4j
@Service
public class PaymentServiceImpl extends ServiceImpl<PaymentMapper, Payment> implements PaymentService {

    @Autowired
    private PaymentMethodMapper paymentMethodMapper;
    
    @Autowired
    private OrderService orderService;

    @Override
    public List<PaymentMethod> getEnabledPaymentMethods() {
        LambdaQueryWrapper<PaymentMethod> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PaymentMethod::getIsEnabled, 1)
                   .orderByAsc(PaymentMethod::getSortOrder);
        
        return paymentMethodMapper.selectList(queryWrapper);
    }

    @Override
    @Transactional
    public Payment createPayment(Long orderId, Long paymentMethodId) {
        // 获取订单信息
        Order order = orderService.getById(orderId);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }
        
        if (order.getStatus() != 1) {
            throw new BusinessException("订单状态不正确，无法支付");
        }

        // 获取支付方式信息
        PaymentMethod paymentMethod = paymentMethodMapper.selectById(paymentMethodId);
        if (paymentMethod == null || paymentMethod.getIsEnabled() != 1) {
            throw new BusinessException("支付方式不可用");
        }

        // 检查是否已有待支付的支付记录
        LambdaQueryWrapper<Payment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Payment::getOrderId, orderId)
                   .in(Payment::getStatus, 0, 1); // 待支付或支付中
        
        Payment existingPayment = getOne(queryWrapper);
        if (existingPayment != null) {
            return existingPayment;
        }

        // 创建支付记录
        Payment payment = new Payment();
        payment.setPaymentNo(generatePaymentNo());
        payment.setOrderId(orderId);
        payment.setOrderNo(order.getOrderNo());
        payment.setUserId(order.getUserId());
        payment.setPaymentMethodId(paymentMethodId);
        payment.setPaymentMethodCode(paymentMethod.getCode());
        payment.setAmount(BigDecimal.valueOf(order.getTotalAmount()));
        payment.setStatus(0); // 待支付
        payment.setCreateTime(LocalDateTime.now());
        payment.setUpdateTime(LocalDateTime.now());

        save(payment);
        return payment;
    }

    @Override
    public Map<String, Object> executePayment(String paymentNo, String paymentMethodCode) {
        Payment payment = getPaymentByNo(paymentNo);
        if (payment == null) {
            throw new BusinessException("支付记录不存在");
        }
        
        if (payment.getStatus() != 0) {
            throw new BusinessException("支付状态不正确");
        }

        Map<String, Object> result = new HashMap<>();
        
        // 根据支付方式执行不同的支付逻辑
        switch (paymentMethodCode) {
            case "alipay":
                result = executeAlipay(payment);
                break;
            case "wechat":
                result = executeWechatPay(payment);
                break;
            case "unionpay":
                result = executeUnionPay(payment);
                break;
            case "balance":
                result = executeBalancePay(payment);
                break;
            case "cod":
                result = executeCodPay(payment);
                break;
            default:
                throw new BusinessException("不支持的支付方式");
        }

        // 更新支付状态为支付中
        payment.setStatus(1);
        payment.setUpdateTime(LocalDateTime.now());
        updateById(payment);

        return result;
    }

    @Override
    public Payment getPaymentByNo(String paymentNo) {
        LambdaQueryWrapper<Payment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Payment::getPaymentNo, paymentNo);
        return getOne(queryWrapper);
    }

    @Override
    @Transactional
    public boolean handlePaymentCallback(String paymentMethodCode, Map<String, Object> callbackData) {
        String paymentNo = (String) callbackData.get("paymentNo");
        String thirdPartyTradeNo = (String) callbackData.get("thirdPartyTradeNo");
        String status = (String) callbackData.get("status");

        Payment payment = getPaymentByNo(paymentNo);
        if (payment == null) {
            log.warn("支付回调：支付记录不存在，paymentNo={}", paymentNo);
            return false;
        }

        // 更新支付状态
        if ("SUCCESS".equals(status)) {
            payment.setStatus(2); // 支付成功
            payment.setPayTime(LocalDateTime.now());
            payment.setThirdPartyTradeNo(thirdPartyTradeNo);
            
            // 更新订单状态为已支付
            orderService.payOrder(payment.getOrderId());
        } else {
            payment.setStatus(3); // 支付失败
        }

        payment.setCallbackTime(LocalDateTime.now());
        payment.setCallbackContent(callbackData.toString());
        payment.setUpdateTime(LocalDateTime.now());

        return updateById(payment);
    }

    @Override
    public boolean cancelPayment(String paymentNo) {
        Payment payment = getPaymentByNo(paymentNo);
        if (payment == null) {
            throw new BusinessException("支付记录不存在");
        }

        if (payment.getStatus() == 2) {
            throw new BusinessException("支付已完成，无法取消");
        }

        payment.setStatus(3); // 支付失败
        payment.setUpdateTime(LocalDateTime.now());
        payment.setRemark("用户取消支付");

        return updateById(payment);
    }

    @Override
    public boolean updatePaymentStatus(String paymentNo, Integer status, String thirdPartyTradeNo) {
        Payment payment = getPaymentByNo(paymentNo);
        if (payment == null) {
            return false;
        }

        payment.setStatus(status);
        payment.setThirdPartyTradeNo(thirdPartyTradeNo);
        payment.setUpdateTime(LocalDateTime.now());

        if (status == 2) {
            payment.setPayTime(LocalDateTime.now());
        }

        return updateById(payment);
    }

    /**
     * 生成支付单号
     */
    private String generatePaymentNo() {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
        return "PAY" + timestamp + uuid.toUpperCase();
    }

    /**
     * 执行支付宝支付（模拟）
     */
    private Map<String, Object> executeAlipay(Payment payment) {
        Map<String, Object> result = new HashMap<>();
        result.put("paymentType", "alipay");
        result.put("message", "支付宝支付成功");

        // 模拟支付宝支付立即成功
        Map<String, Object> callbackData = new HashMap<>();
        callbackData.put("paymentNo", payment.getPaymentNo());
        callbackData.put("thirdPartyTradeNo", "ALIPAY" + System.currentTimeMillis());
        callbackData.put("status", "SUCCESS");

        handlePaymentCallback("alipay", callbackData);

        return result;
    }

    /**
     * 执行微信支付（模拟）
     */
    private Map<String, Object> executeWechatPay(Payment payment) {
        Map<String, Object> result = new HashMap<>();
        result.put("paymentType", "wechat");
        result.put("message", "微信支付成功");

        // 模拟微信支付立即成功
        Map<String, Object> callbackData = new HashMap<>();
        callbackData.put("paymentNo", payment.getPaymentNo());
        callbackData.put("thirdPartyTradeNo", "WECHAT" + System.currentTimeMillis());
        callbackData.put("status", "SUCCESS");

        handlePaymentCallback("wechat", callbackData);

        return result;
    }

    /**
     * 执行银联支付（模拟）
     */
    private Map<String, Object> executeUnionPay(Payment payment) {
        Map<String, Object> result = new HashMap<>();
        result.put("paymentType", "unionpay");
        result.put("message", "银联支付成功");

        // 模拟银联支付立即成功
        Map<String, Object> callbackData = new HashMap<>();
        callbackData.put("paymentNo", payment.getPaymentNo());
        callbackData.put("thirdPartyTradeNo", "UNIONPAY" + System.currentTimeMillis());
        callbackData.put("status", "SUCCESS");

        handlePaymentCallback("unionpay", callbackData);

        return result;
    }

    /**
     * 执行余额支付（模拟）
     */
    private Map<String, Object> executeBalancePay(Payment payment) {
        Map<String, Object> result = new HashMap<>();
        result.put("paymentType", "balance");
        result.put("message", "余额支付成功");
        
        // 模拟余额支付立即成功
        Map<String, Object> callbackData = new HashMap<>();
        callbackData.put("paymentNo", payment.getPaymentNo());
        callbackData.put("thirdPartyTradeNo", "BALANCE" + System.currentTimeMillis());
        callbackData.put("status", "SUCCESS");
        
        handlePaymentCallback("balance", callbackData);
        
        return result;
    }

    /**
     * 执行货到付款（模拟）
     */
    private Map<String, Object> executeCodPay(Payment payment) {
        Map<String, Object> result = new HashMap<>();
        result.put("paymentType", "cod");
        result.put("message", "货到付款订单已确认");
        
        // 货到付款直接标记为支付成功
        Map<String, Object> callbackData = new HashMap<>();
        callbackData.put("paymentNo", payment.getPaymentNo());
        callbackData.put("thirdPartyTradeNo", "COD" + System.currentTimeMillis());
        callbackData.put("status", "SUCCESS");
        
        handlePaymentCallback("cod", callbackData);
        
        return result;
    }
}
